﻿using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using RpcHelper.Error;

namespace RpcHelper
{
    public class ErrorManage : ILocalError
    {
        private ILocalErrorManage _ErrorManage;
        private bool _IsChange = false;
        private string _Lang = "zh";
        public string Lang
        {
            get;
        }
        public bool IsChange { get => _IsChange; set => _IsChange = value; }

        private readonly ConcurrentDictionary<string, ErrorMsg> _ErrorMsg = new ConcurrentDictionary<string, ErrorMsg>();
        public ErrorMsg[] Errors { get => _ErrorMsg.Values.ToArray(); }
        internal ErrorManage(string path, ILocalErrorManage localError)
        {
            this._ErrorManage = localError;
            this._LoadErrorXml(path);
        }
        
        private void _LoadErrorXml(string path)
        {
            FileInfo file = new FileInfo(path);
            if (file.Exists)
            {
                string xml = null;
                using (StreamReader ready = new StreamReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Delete), Encoding.UTF8))
                {
                    xml = ready.ReadToEnd();
                    ready.Close();
                }
                if (string.IsNullOrEmpty(xml))
                {
                    return;
                }
                this._LoadXml(xml);
                this._IsChange = false;
            }
            else
            {
                new InfoLog("加载本地错误信息文件,未找到!", path).Save();
            }
        }
        private void _LoadXml(string xml)
        {
            XmlDataDocument doc = new XmlDataDocument();
            doc.LoadXml(xml);
            this._Lang = doc.DocumentElement.GetAttribute("lang");
            if (string.IsNullOrEmpty(this._Lang))
            {
                return;
            }
            foreach (XmlNode node in doc.DocumentElement.ChildNodes)
            {
                if (node.HasChildNodes)
                {
                    string name = node.Name;
                    foreach (XmlNode i in node.ChildNodes)
                    {
                        ErrorMsg msg = new ErrorMsg()
                        {
                            Lang = _Lang
                        };
                        msg.InitErrorMsg(name, i);
                        if (!this._ErrorMsg.ContainsKey(msg.ErrorCode))
                        {
                            this._ErrorMsg.TryAdd(msg.ErrorCode, msg);
                        }
                    }
                }
            }
        }
      
        public bool TryGet(string code, out ErrorMsg error)
        {
            if (this._ErrorMsg.TryGetValue(code, out error))
            {
                return true;
            }
            else if(this._ErrorManage.RemoteGet(this, code, out error))
            {
                this.Add(error);
                return true;
            }
            return false;
        }
        public void Drop(string code)
        {
            if (!this._ErrorMsg.TryRemove(code, out ErrorMsg msg))
            {
                this._IsChange = true;
                this._ErrorManage.TriggerDrop(this, msg);
            }
        }
        public bool Add(ErrorMsg msg)
        {
            if (!this._ErrorMsg.ContainsKey(msg.ErrorCode))
            {
                if(this._ErrorMsg.TryAdd(msg.ErrorCode, msg))
                {
                    this._IsChange = true;
                    return true;
                }
            }
            return false;
        }
    }
}
